package com.nxzsxt;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class ProjectRefactorTool {

    private static final Logger logger = Logger.getLogger(ProjectRefactorTool.class.getName());

    private String projectPath;
    private String oldPrefix;
    private String newPrefix;
    private String newPackageName;
    private String oldPackageName;
    private String oldGroupId;
    private String newGroupId;

    public ProjectRefactorTool(String projectPath, String oldPrefix, String newPrefix, String newPackageName, String oldPackageName, String oldGroupId, String newGroupId) {
        this.projectPath = projectPath;
        this.oldPrefix = oldPrefix;
        this.newPrefix = newPrefix;
        this.newPackageName = newPackageName;
        this.oldPackageName = oldPackageName;
        this.oldGroupId = oldGroupId;
        this.newGroupId = newGroupId;
    }

    public void refactor() throws IOException {
        logger.info("Starting refactoring process...");

        // Rename modules in the root pom.xml
        updateRootPom();

        // Rename module directories and update their pom.xml files
        renameModulesAndPoms(projectPath);

        // Update package declarations in Java source files
        updateJavaFiles(projectPath);

        logger.info("Refactoring completed successfully.");
    }

    private void updateRootPom() throws IOException {
        Path rootPomPath = Paths.get(projectPath, "pom.xml");
        logger.info("Updating root pom.xml at: " + rootPomPath);

        String content = new String(Files.readAllBytes(rootPomPath));

        // Update groupId
        content = content.replaceAll("<groupId>" + oldGroupId + "</groupId>", "<groupId>" + newGroupId + "</groupId>");

        // Update module names
        content = content.replaceAll("<module>" + oldPrefix + "-([^<]+)</module>", "<module>" + newPrefix + "-$1</module>");
        content = content.replaceAll("<module>" + oldPrefix + "/([^<]+)</module>", "<module>" + newPrefix + "/$1</module>");
        content = content.replaceAll("<module>" + oldPrefix + "</module>", "<module>" + newPrefix + "</module>"); // 处理直接在根目录下的模块

        // Update artifactIds in dependencies
        content = content.replaceAll("<artifactId>" + oldPrefix + "-([^<]+)</artifactId>", "<artifactId>" + newPrefix + "-$1</artifactId>");

        Files.write(rootPomPath, content.getBytes());
        logger.info("Updated root pom.xml successfully.");
    }

    private void renameModulesAndPoms(String currentPath) throws IOException {
        File rootDir = new File(currentPath);
        File[] modules = rootDir.listFiles(File::isDirectory);
        if (modules != null) {
            for (File module : modules) {
                String moduleName = module.getName();
                if (moduleName.startsWith(oldPrefix)) {
                    String newModuleName = moduleName.replaceFirst(oldPrefix, newPrefix);
                    File newModuleDir = new File(rootDir, newModuleName);
                    module.renameTo(newModuleDir);
                    logger.info("Renamed module directory from " + moduleName + " to " + newModuleName);

                    Path pomPath = Paths.get(newModuleDir.getAbsolutePath(), "pom.xml");
                    if (Files.exists(pomPath)) {
                        logger.info("Updating pom.xml at: " + pomPath);

                        String content = new String(Files.readAllBytes(pomPath));

                        // Update groupId
                        content = content.replaceAll("<groupId>" + oldGroupId + "</groupId>", "<groupId>" + newGroupId + "</groupId>");

                        // Update artifactId
                        content = content.replaceAll("<artifactId>" + oldPrefix + "-([^<]+)</artifactId>", "<artifactId>" + newPrefix + "-$1</artifactId>");

                        // Update module names
                        content = content.replaceAll("<module>" + oldPrefix + "-([^<]+)</module>", "<module>" + newPrefix + "-$1</module>");
                        content = content.replaceAll("<module>" + oldPrefix + "/([^<]+)</module>", "<module>" + newPrefix + "/$1</module>");
                        content = content.replaceAll("<module>" + oldPrefix + "</module>", "<module>" + newPrefix + "</module>"); // 处理直接在根目录下的模块

                        // Update artifactIds in dependencies
                        content = content.replaceAll("<artifactId>" + oldPrefix + "-([^<]+)</artifactId>", "<artifactId>" + newPrefix + "-$1</artifactId>");

                        Files.write(pomPath, content.getBytes());
                        logger.info("Updated pom.xml successfully.");
                    }

                    // Recursively rename sub-modules and update their pom.xml files
                    renameModulesAndPoms(newModuleDir.getAbsolutePath());
                } else {
                    // Check for subdirectories that might contain modules
                    if (module.isDirectory()) {
                        renameModulesAndPoms(module.getAbsolutePath());
                    }
                }
            }
        }
    }

    private void updateJavaFiles(String currentPath) throws IOException {
        File rootDir = new File(currentPath);
        File[] modules = rootDir.listFiles(File::isDirectory);
        if (modules != null) {
            for (File module : modules) {
                // 处理所有模块，包括尚未重命名的模块
                if (module.isDirectory()) {
                    Path srcMainJavaPath = Paths.get(module.getAbsolutePath(), "src", "main", "java");
                    Path srcTestJavaPath = Paths.get(module.getAbsolutePath(), "src", "test", "java");

                    updatePackageDeclarations(srcMainJavaPath);
                    updatePackageDeclarations(srcTestJavaPath);

                    // Recursively update Java files in sub-modules
                    updateJavaFiles(module.getAbsolutePath());
                }
            }
        }
    }

    private void updatePackageDeclarations(Path path) throws IOException {
        if (Files.exists(path)) {
            logger.info("Updating Java files in directory: " + path);

            try (Stream<Path> paths = Files.walk(path)) {
                paths.filter(Files::isRegularFile)
                        .filter(p -> p.toString().endsWith(".java"))
                        .forEach(p -> {
                            try {
                                logger.info("Updating file: " + p);

                                String content = new String(Files.readAllBytes(p));

                                // Update package declaration
                                if (oldPackageName != null && !oldPackageName.isEmpty()) {
                                    // Use a regular expression to match only package declarations starting with 'sinuo'
                                    content = content.replaceFirst("^package " + Pattern.quote(oldPackageName) + "(\\.[^;]+)?;", "package " + newPackageName + "$1;");
                                }

                                // Update import statements
                                Pattern importPattern = Pattern.compile("import (" + Pattern.quote(oldPackageName) + "\\.)([^;]+);");
                                Matcher matcher = importPattern.matcher(content);
                                StringBuilder sb = new StringBuilder();
                                while (matcher.find()) {
                                    String newImport = matcher.group(1).replace(oldPackageName, newPackageName) + matcher.group(2);
                                    matcher.appendReplacement(sb, "import " + newImport + ";");
                                }
                                matcher.appendTail(sb);
                                content = sb.toString();

                                Files.write(p, content.getBytes());
                                logger.info("Updated file: " + p);
                            } catch (IOException e) {
                                logger.severe("Error updating file: " + p + ". Error: " + e.getMessage());
                                e.printStackTrace();
                            }
                        });
            }
        }
    }

    public static void main(String[] args) {
        try {
            ProjectRefactorTool tool = new ProjectRefactorTool("D:\\project\\test", "sinuo", "zsxt", "zsxt", "sinuo", "com.sinuo", "com.zsxt");
            tool.refactor();
            System.out.println("Refactoring completed successfully.");
        } catch (IOException e) {
            logger.severe("Refactoring failed. Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
